package com.socialrss.instagramkit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

import org.json.JSONObject;
import org.json.JSONTokener;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.socialrss.constants.SocialNetworkNames.SocialNetKeys;
import com.socialrss.instagramkit.InstagramDialog.OAuthDialogListener;
import com.socialrss.utils.SocialRssModel;

/**
 * 
 * @author Sefa Shnkc <shnkoc@gmail.com>
 * 
 */
public class InstagramApp {

	private InstagramDialog mDialog;
	private OAuthAuthenticationListener mListener;
	private ProgressDialog mProgress;
	private String mAuthUrl;
	private String mAccessToken;
	private Context mCtx;

	private String mClientId;
	private String mClientSecret;
	
	private String userId, userName, fullname, request_token;


//	private static int WHAT_FINALIZE = 0;
	private static int WHAT_ERROR = 1;
	private static int WHAT_FETCH_INFO = 2;

	/**
	 * Callback url, as set in 'Manage OAuth Costumers' page
	 * (https://developer.github.com/)
	 */

	public static String mCallbackUrl = "";

	private static final String TAG = "InstagramAPI";

	public InstagramApp(Context context) {

		mClientId = InstagramConstants.CLIENT_ID;
		mClientSecret = InstagramConstants.CLIENT_SECRET;
		mCtx = context;;
		mCallbackUrl = InstagramConstants.CALLBACKURL;
		mAuthUrl = InstagramConstants.AUTHURL + "?client_id=" + mClientId + "&redirect_uri="
				+ mCallbackUrl + "&response_type=code&display=touch&scope=likes+comments+relationships";

		OAuthDialogListener listener = new OAuthDialogListener() {
			@Override
			public void onComplete(String code) {
				request_token = code;
				getAccessToken(code);
			}

			@Override
			public void onError(String error) {
				mListener.onFail("Authorization failed");
			}
		};
		
		mListener = new OAuthAuthenticationListener() {
			
			@Override
			public void onSuccess() {
				SocialRssModel.Instance(null).addNewSocialNetworkReqToken(SocialNetKeys.ins.toString(), request_token, mAccessToken, userName,
						userId, fullname);
				AlertDialog.Builder builder1 = new AlertDialog.Builder(mCtx);
				builder1.setMessage("Authentication has been completed.")
					.setPositiveButton("OK", new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							Log.d(InstagramConstants.LOG_INFO, "Instagram Account has been added!");
							dialog.dismiss();
						}
					});
				AlertDialog mydial = builder1.create();
				mydial.show();
				
			}
			
			@Override
			public void onFail(String error) {
				AlertDialog.Builder builder1 = new AlertDialog.Builder(mCtx);
				builder1.setMessage("Authentication failed.")
					.setPositiveButton("OK", new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					});
				AlertDialog mydial = builder1.create();
				mydial.show();
				
			}
		};
		mDialog = new InstagramDialog(context, mAuthUrl, listener);
		mProgress = new ProgressDialog(context);
		mProgress.setCancelable(false);
	}

	private void getAccessToken(final String code) {
		mProgress.setMessage("Getting access token ...");
		mProgress.show();

		new Thread() {
			@Override
			public void run() {
				Log.i(TAG, "Getting access token");
				int what = WHAT_FETCH_INFO;
				try {
					URL url = new URL(InstagramConstants.TOKENURL);
					//URL url = new URL(mTokenUrl + "&code=" + code);
					Log.i(TAG, "Opening Token URL " + url.toString());
					HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
					urlConnection.setRequestMethod("POST");
					urlConnection.setDoInput(true);
					urlConnection.setDoOutput(true);
					//urlConnection.connect();
					OutputStreamWriter writer = new OutputStreamWriter(urlConnection.getOutputStream());
					writer.write("client_id="+mClientId+
								"&client_secret="+mClientSecret+
								"&grant_type=authorization_code" +
								"&redirect_uri="+mCallbackUrl+
								"&code=" + code);
				    writer.flush();
					String response = streamToString(urlConnection.getInputStream());
					Log.i(TAG, "response " + response);
					JSONObject jsonObj = (JSONObject) new JSONTokener(response).nextValue();

					mAccessToken = jsonObj.getString("access_token");
					Log.i(TAG, "Got access token: " + mAccessToken);

					userId = jsonObj.getJSONObject("user").getString("id");
					userName = jsonObj.getJSONObject("user").getString("username");
					fullname = jsonObj.getJSONObject("user").getString("full_name");					
					
					
					

				} catch (Exception ex) {
					what = WHAT_ERROR;
					ex.printStackTrace();
				}

				mHandler.sendMessage(mHandler.obtainMessage(what, 1, 0));
			}
		}.start();
	}



	@SuppressLint("HandlerLeak")
	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			if (msg.what == WHAT_ERROR) {
				mProgress.dismiss();
				if(msg.arg1 == 1) {
					mListener.onFail("Failed to get access token");
				}
				else if(msg.arg1 == 2) {
					mListener.onFail("Failed to get user information");
				}
			} 
			else if(msg.what == WHAT_FETCH_INFO) {
				//fetchUserName();
				mProgress.dismiss();
				mListener.onSuccess();
			}
			else {
				mProgress.dismiss();
				mListener.onSuccess();
			}
		}
	};

	public boolean hasAccessToken() {
		return (mAccessToken == null) ? false : true;
	}

	public void setListener(OAuthAuthenticationListener listener) {
		mListener = listener;
	}


	public void authorize() {
		mDialog.show();
	}

	private String streamToString(InputStream is) throws IOException {
		String str = "";

		if (is != null) {
			StringBuilder sb = new StringBuilder();
			String line;

			try {
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(is));

				while ((line = reader.readLine()) != null) {
					sb.append(line);
				}

				reader.close();
			} finally {
				is.close();
			}

			str = sb.toString();
		}

		return str;
	}


	public interface OAuthAuthenticationListener {
		public abstract void onSuccess();
		public abstract void onFail(String error);
	}
}
